package com.ebupt.migu.banner2.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.ebupt.migu.banner2.entity.ApiQueryBean;
import com.ebupt.migu.banner2.entity.Banner2Vo;
import com.ebupt.migu.banner2.entity.ResultMsg;
import com.ebupt.migu.banner2.pojo.Banner2RedisBean;
import com.ebupt.migu.banner2.pojo.Banner2Rule;
import com.ebupt.migu.banner2.service.Banner2Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;


/**
 * @author tz
 */
@Slf4j
@Service
public class Banner2ServiceImpl implements Banner2Service {

    /**
     * redis缓存的banner2活动列表
     */
    private static final String BANNER2_LIST = "BANNER2_LIST";

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public ResultMsg query(ApiQueryBean bean) {
        log.info("request params:{}", bean);
        List<Banner2Vo> vo = new ArrayList<>();
        // 取redis列表中进行中的活动
        Set<String> members = redisTemplate.opsForSet().members(BANNER2_LIST);
        if (members != null && members.size() > 0) {
            members.forEach(m -> {
                try {
                    Banner2RedisBean banner2RedisBean = JSON.parseObject(String.valueOf(redisTemplate.opsForValue().get(m)), Banner2RedisBean.class);
                    // 判断用户是否满足banner组条件
                    banner2RedisBean.getBanner().forEach(banner -> {
                        log.info("活动ID：{} --> banner{}",banner2RedisBean.getActivityId(),banner.getShowSeq());
                        if (customerFilter(banner.getGroupId(),bean.getExtra())
                                && ruleFilter(banner.getRules(),bean.getExtra())) {
                            Banner2Vo bv = new Banner2Vo();
                            BeanUtils.copyProperties(banner,bv);
                            vo.add(bv);
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        } else {
            log.info("没有进行中的banner2策略");
        }
        ResultMsg res = new ResultMsg();
        res.setMessage("SUCCESS");
        res.setData(vo);
        return res;
    }

    /**
     * 条件筛选过滤：指定客群包含关系过滤
     *
     * @param extra
     * @return
     */
    private boolean customerFilter(String customerId, HashMap<String, String> extra) {
        AtomicBoolean flag = new AtomicBoolean(false);
        if (StringUtils.isNotEmpty(customerId)) {
            List<String> list = Arrays.asList(customerId.split(","));
            list.forEach(l -> {
                String uid = Optional.ofNullable(extra.get("uid")).isPresent() ? extra.get("uid") : "";
                String msisdn = Optional.ofNullable(extra.get("msisdn")).isPresent() ? extra.get("msisdn") : "";
                if (redisTemplate.opsForSet().isMember(l + "-uid", uid)
                        || redisTemplate.opsForSet().isMember(l + "-phone", msisdn)) {
                    flag.set(true);
                }
                log.info("人群：{}，判定结果：{}", l,flag.get());
            });
            log.info("人群最终判定：{}", flag.get());
        } else {
            flag.set(true);
            log.info("没有指定包含人群，默认判定：true");
        }
        return flag.get();
    }

    /**
     * 条件筛选过滤：筛选条件过滤
     * 
     * @param rules
     * @param extra
     * @return
     */
    private boolean ruleFilter(List<Banner2Rule> rules, HashMap<String, String> extra) {
        AtomicBoolean atomic = new AtomicBoolean(false);
        if (null == rules || rules.isEmpty()) {
            log.info("没有指定个性化条件，默认判定：true");
            return true;
        }
        String ua = extra.get("ua");
        String version = extra.get("version");
        if (ua == null || ua.isEmpty() || version == null || version.isEmpty()) {
            log.info("入参缺失，默认判定：true");
            return true;
        }
        try {
            rules.forEach(rule -> {
                if (rule.getRuleKey().equals(ua)) {
                    switch (rule.getOperator()) {
                        // 等于
                        case 1:
                            if (version.equals(rule.getRuleValue())) {
                                log.info("筛选条件：{} 等于 {}，传入参数值：{}, 判定结果：{}", rule.getRuleKey(),
                                        rule.getRuleValue(), version, "true");
                                atomic.set(true);
                            }
                            break;
                        // 小于
                        case 2:
                            if (version.compareTo(rule.getRuleValue()) < 0) {
                                log.info("筛选条件：{} 小于 {}，传入参数值：{}, 判定结果：{}", rule.getRuleKey(),
                                        rule.getRuleValue(), version, "true");
                                atomic.set(true);
                            }
                            break;
                        // 大于
                        case 3:
                            if (version.compareTo(rule.getRuleValue()) > 0) {
                                log.info("筛选条件：{} 大于 {}，传入参数值：{}, 判定结果：{}", rule.getRuleKey(),
                                        rule.getRuleValue(), version, "true");
                                atomic.set(true);
                            }
                            break;
                        // 小于等于
                        case 4:
                            if (version.compareTo(rule.getRuleValue()) <= 0) {
                                log.info("筛选条件：{} 小于等于 {}，传入参数值：{}, 判定结果：{}", rule.getRuleKey(),
                                        rule.getRuleValue(), version, "true");
                                atomic.set(true);
                            }
                            break;
                        // 大于等于
                        case 5:
                            if (version.compareTo(rule.getRuleValue()) >= 0) {
                                log.info("筛选条件：{} 大于等于 {}，传入参数值：{}, 判定结果：{}", rule.getRuleKey(),
                                        rule.getRuleValue(), version, "true");
                                atomic.set(true);
                            }
                            break;
                        // 不等于
                        case 6:
                            if (!version.equals(rule.getRuleValue())) {
                                log.info("筛选条件：{} 不等于 {}，传入参数值：{}, 判定结果：{}", rule.getRuleKey(),
                                        rule.getRuleValue(), version, "true");
                                atomic.set(true);
                            }
                            break;
                        default:
                            break;
                    }
                } else {
                    log.info("不匹配的筛选条件：{}，判定结果：{}", rule.getRuleKey(), "false");
                }
            });
            log.info("条件最终判定：{}", atomic.get());
            return atomic.get();
        } catch (Exception e) {
            return false;
        }
    }
}